package middleware

import (
	"gostore/dao/relation"
	m "gostore/model"
	"gostore/util"
	"gostore/util/log"
	"strconv"
	"strings"
)

var auth *AuthManager

func GetAuthManager() *AuthManager {
	if auth == nil {
		auth = &AuthManager{}
		auth.LoadPolicy()
	}

	return auth
}

type Permission map[string]map[string][]string
type AuthManager struct {
	permisssions Permission
}

// Check role authorization
//roleList is list of role id
func (a AuthManager) Check(roleList []string, path, method string) bool {
	path, method = strings.Join(util.Split(path, "/"), "/"), strings.ToLower(method)
	log.Debug("auth check ", strings.Join(roleList, ","), path, method)

	if roleList != nil && len(roleList) > 0 {
		// log.Debug("check roleist")
		m := a.permisssions[path]
		if m != nil {
			// log.Debug("check path")
			roles := m[method]
			if roles != nil {
				// log.Debug("check roles")
				for _, r1 := range roles {
					for _, r2 := range roleList {
						// log.Debug("check ", "["+r1+"]", "'r2'")
						if r1 == r2 {
							return true
						}
					}
				}
			}
		}
	}

	return false
}

// load permission rules from db
func (a *AuthManager) LoadPolicy() error {

	list := []m.RelationRolePolicy{}
	err := relation.RolePolicyDao.LoadAllWithRolePolicy(&list)
	if err != nil {
		log.Debug(err.Error())
		return err
	}
	a.permisssions = make(Permission)
	for _, rel := range list {
		role := rel.Role.Id
		if role != 0 {
			path, method := strings.Join(util.Split(rel.Policy.Path, "/"), "/"), strings.ToLower(rel.Policy.Method)

			if _, ok := a.permisssions[path]; !ok {
				a.permisssions[path] = make(map[string][]string)
			}
			log.Debug("load policy ", path, method, role)
			a.permisssions[path][method] = append(a.permisssions[path][method], strconv.Itoa(role))
		}
	}

	return nil
}

// func (*AuthManager) AddPolicy(path string, method string, roles []string) error {

// 	return nil
// }

// func (*AuthManager) SavePolicy() error {

// 	return nil
// }

// func (*AuthManager) RemovePolicy(sec string, ptype string, rule []string) error {
// 	return nil
// }
